package data;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.FileNotFoundException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;

import user.User;
import user.UserType;


public class DatabaseTest
{
	private Database myTestDatabase;
	
	@Before
	public void init()
	{
		try {
			myTestDatabase = new Database("../");
		} catch (FileNotFoundException e) {
			System.err.println("Cannot Read/Write to current location.");
		}
	}
	
	/**
	 * Tests to see that a user was added to the Database correctly using a pre-
	 * instantialized user.
	 */
	@Test
	public void testAddUserSingleType()
	{
		final UserType[] type = {UserType.STUDENT};
		final int id = 1039197;
		final String name = "Thach";
		User test = new User(id, name, type);
		myTestDatabase.addUser(test);
		
		System.out.println(myTestDatabase.getTeachers());
		assertEquals("Did not end up in user list", test, myTestDatabase.getUser(id));
		assertEquals(0, myTestDatabase.getAvisors().size());
		assertEquals(0, myTestDatabase.getTeachers().size());
		assertEquals(1, myTestDatabase.getStudents().size());
		assertTrue(myTestDatabase.getStudents().contains(test));
	}
	
	/**
	 * Test to see that the user was added to both student and adviser lists in
	 * the database.
	 */
	@Test
	public void testAddUserTwoTypes()
	{
		final UserType[] type = {UserType.STUDENT, UserType.ADVISER};
		final int id = 1039197;
		final String name = "Thach";
		User test = new User(id, name, type);
		myTestDatabase.addUser(test);
		assertEquals(test, myTestDatabase.getUser(id));
		assertEquals(1, myTestDatabase.getAvisors().size());
		assertEquals(0, myTestDatabase.getTeachers().size());
		assertEquals(1, myTestDatabase.getStudents().size());
		assertTrue(myTestDatabase.getStudents().contains(test));
		assertTrue(myTestDatabase.getAvisors().contains(test));
	}
	
	/**
	 * Test to see that the user was added to all user lists except scheduler.
	 */
	@Test
	public void testAddUserThreeTypes()
	{
		final UserType[] type = {UserType.STUDENT, UserType.ADVISER, UserType.TEACHER};
		final int id = 1039197;
		final String name = "Thach";
		User test = new User(id, name, type);
		myTestDatabase.addUser(test);
		assertEquals(test, myTestDatabase.getUser(id));
		assertEquals(1, myTestDatabase.getAvisors().size());
		assertEquals(1, myTestDatabase.getTeachers().size());
		assertEquals(1, myTestDatabase.getStudents().size());
		assertTrue(myTestDatabase.getStudents().contains(test));
		assertTrue(myTestDatabase.getAvisors().contains(test));
		assertTrue(myTestDatabase.getTeachers().contains(test));
	}
	
	/**
	 * Test to see that user was only added to the user database.
	 */
	@Test
	public void testAddUserScheduler()
	{
		final UserType[] type = {UserType.SCHEDULER};
		final int id = 1039197;
		final String name = "Thach";
		User test = new User(id, name, type);
		myTestDatabase.addUser(test);
		assertEquals(test, myTestDatabase.getUser(id));
		assertEquals(0, myTestDatabase.getAvisors().size());
		assertEquals(0, myTestDatabase.getTeachers().size());
		assertEquals(0, myTestDatabase.getStudents().size());
	}
	
	@Test
	public void testGetStudentClassConstraintsOverFivePercent() {
		final UserType[] type = {UserType.STUDENT};
		final int id = 1039197;
		final String name = "Thach";
		User temp = new User(id, name, type);
		ClassPreference test = new ClassPreference("TCSS142", "INTRODUCTION TO OBJECT-ORIENTED PROGRAMMING", 'A', 5);
		temp.addClass(test, UserType.STUDENT) ;
		myTestDatabase.addUser(temp);
		List<ClassPreference> testPref = myTestDatabase.getStudentClassConstraints();
		assertTrue(testPref.contains(test));
	}
	
	@Test
	public void testGetStudentClassConstraintsLessThanFivePercent() {
		final UserType[] type = {UserType.STUDENT};
		final int id = 1039197;
		final String name = "Thach";
		User testUser = new User(id, name, type);
		ClassPreference test = new ClassPreference("TCSS142", "INTRODUCTION TO OBJECT-ORIENTED PROGRAMMING", 'A', 5);
		testUser.addClass(test, UserType.STUDENT) ;
		myTestDatabase.addUser(testUser);
		for (int i = 0; i < 19; i++) {
			User temp = new User(i, "Joe", UserType.STUDENT);
			myTestDatabase.addUser(temp);
		}
		List<ClassPreference> testPref = myTestDatabase.getStudentClassConstraints();
		assertFalse(testPref.contains(test));
	}
	
	@Test
	public void testGetStudentTimeConstraintsOverFivePercent() {
		final UserType[] type = {UserType.STUDENT};
		final int id = 1039197;
		final String name = "Thach";
		User temp = new User(id, name, type);
		Set<ClassDays> days = new HashSet<ClassDays>();
		days.add(ClassDays.MONDAY);
		TimeSlot test = new TimeSlot(days, 5, 9);
		temp.addTime(test, UserType.STUDENT) ;
		myTestDatabase.addUser(temp);
		List<TimeSlot> testPref = myTestDatabase.getStudentTimeConstraints();
		assertTrue(testPref.contains(test));
	}
	
	@Test
	public void testGetStudentTimeConstraintsLessThanFivePercent() {
		final UserType[] type = {UserType.STUDENT};
		final int id = 1039197;
		final String name = "Thach";
		User testUser = new User(id, name, type);
		Set<ClassDays> days = new HashSet<ClassDays>();
		days.add(ClassDays.MONDAY);
		TimeSlot test = new TimeSlot(days, 5, 9);
		testUser.addTime(test, UserType.STUDENT) ;
		myTestDatabase.addUser(testUser);
		for (int i = 0; i < 19; i++) {
			User temp = new User(i, "Joe", UserType.STUDENT);
			myTestDatabase.addUser(temp);
		}
		List<TimeSlot> testPref = myTestDatabase.getStudentTimeConstraints();
		assertFalse(testPref.contains(test));
	}
}
